package cn.cloudtogo.server.module.datasource;

import cn.cloudtogo.common.DatasourceCreateService;
import cn.cloudtogo.common.model.ExternalDatasourceDao;
import cn.cloudtogo.common.model.ExternalDatasourceModel;
import cn.cloudtogo.common.types.ConnectString;
import cn.cloudtogo.common.types.DatasourceCreateObject;
import cn.cloudtogo.common.types.ObjectId;
import cn.cloudtogo.common.types.RequestHeaderObject;
import cn.cloudtogo.common.util.JdbcConnectionHelper;
import cn.cloudtogo.common.util.MongoConnectionHelper;
import cn.cloudtogo.server.atomapi.ApiTokenCreateParam;
import cn.cloudtogo.server.atomapi.event.GlobalApiTokenCreatedEvent;
import cn.cloudtogo.server.mongo.SpringMongoTemplateContext;
import cn.cloudtogo.server.mysql.SpringJdbcTemplateContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

import static cn.cloudtogo.common.util.StringHelper.pretty;

/**
 * @author yaolianhua789@gmail.com
 **/
@Service
@Slf4j
public class ExternalDatasourceCreateService implements DatasourceCreateService {

    private final ExternalDatasourceDao externalDatasourceDao;
    private final SpringJdbcTemplateContext jdbcTemplateContext;
    private final SpringMongoTemplateContext mongoTemplateContext;
    private final ApplicationEventPublisher eventPublisher;

    public ExternalDatasourceCreateService(ExternalDatasourceDao externalDatasourceDao,
                                           SpringJdbcTemplateContext jdbcTemplateContext,
                                           SpringMongoTemplateContext mongoTemplateContext,
                                           ApplicationEventPublisher eventPublisher) {
        this.externalDatasourceDao = externalDatasourceDao;
        this.jdbcTemplateContext = jdbcTemplateContext;
        this.mongoTemplateContext = mongoTemplateContext;
        this.eventPublisher = eventPublisher;
    }

    @Override
    public void process(String uuid) {
        ApiTokenCreateParam ofGlobal = ApiTokenCreateParam.ofGlobal(uuid, "Global");
        eventPublisher.publishEvent(new GlobalApiTokenCreatedEvent(ofGlobal));
    }

    @Override
    public String refreshTemplate(ExternalDatasourceModel model, DatasourceCreateObject createObject) {
        ConnectString connectString = createObject.getConnectString();

        RequestHeaderObject headerObject = RequestHeaderObject.ofModel(model);
        switch (createObject.getType()) {
            case Mysql:
                JdbcTemplate jdbcTemplate = JdbcConnectionHelper.getJdbcTemplate(connectString);

                String sql = String.format("create schema if not exists `%s`", connectString.getSchema());
                log.debug(pretty(headerObject, "Create schema", null, sql));
                jdbcTemplate.execute(sql);

                jdbcTemplateContext.putJdbcTemplate(headerObject, jdbcTemplate);
                break;
            case Mongo:
                MongoTemplate mongoTemplate = MongoConnectionHelper.getMongoTemplate(connectString);
                mongoTemplateContext.putMongoTemplate(headerObject, mongoTemplate);
                break;
            default:
                break;
        }
        return model.getUuid();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ExternalDatasourceModel modelSaved(DatasourceCreateObject createObject) {
        String uuid = ObjectId.get().toHexString();
        ConnectString connectString = createObject.getConnectString();
        String baseUrl = createObject.obtainConnectUrl();

        //save external datasource
        ExternalDatasourceModel externalDatasourceModel = new ExternalDatasourceModel();
        externalDatasourceModel.setUuid(uuid);
        externalDatasourceModel.setOpenid(createObject.getOpenid());
        externalDatasourceModel.setProject(createObject.obtainProject());
        externalDatasourceModel.setName(createObject.getName());
        externalDatasourceModel.setUrl(baseUrl);
        externalDatasourceModel.setSchema(createObject.getSchema());
        externalDatasourceModel.setUsername(connectString.getCredential().getUser());
        externalDatasourceModel.setPassword(connectString.getCredential().getPassword());
        externalDatasourceModel.setType(createObject.getType());
        externalDatasourceModel.setHost(connectString.getEndpoint().getHost());
        externalDatasourceModel.setPort(connectString.getEndpoint().getPort());
        externalDatasourceModel.setCreateAt(LocalDateTime.now());

        externalDatasourceDao.save(externalDatasourceModel);

        return externalDatasourceModel;

    }


}
